package com.crawler;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;

import com.crawler.dto.Parameter;
import com.crawler.html.impl.XTY_Site;
import com.crawler.thr.ExecutorService;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.util.concurrent.FutureCallback;

public class Crawler {
    // 并发线程数
    private int threadCount = 10;

    private static class InstanceHolder {
        private static final Crawler instatnce = new Crawler();
    }

    private Crawler() {
        super();
    }

    public static Crawler getInstance() {
        return InstanceHolder.instatnce;
    }

    /**
     * 方法描述： 手动输入验证码 爬虫
     * 
     * @author TL
     * @date 2016年6月19日 下午2:59:50
     * @param parameterS
     * @return
     */
    public List<Parameter> enterCodeManuallyCrawler(List<Parameter> parameterS) {
        Preconditions.checkNotNull(parameterS);
        class RunCallable implements Callable<Parameter> {
            private Parameter parameter = null;
            public RunCallable(Parameter parameter) {
                this.parameter = parameter;
            }
            @Override
            public Parameter call() throws Exception {
                Parameter par = null;
                do {
                    try {
                        par = new Parameter();
                        par = new XTY_Site().setParameter(parameter).enterCodeManually().resultsOf();
                    } catch (Exception e) {
                        par = parameter;
                        parameter.setExc(e);
                    }
                } while (par.getExc()!=null||!Strings.isNullOrEmpty(par.getContent()));
                
                return par;
            }
        }
        // 创建线程池
        ExecutorService service = new ExecutorService(threadCount);
        ResultCallback callback = new ResultCallback();
        for (final Parameter parameter : parameterS) {
            service.addCallback(new RunCallable(parameter), callback);
        }

        service.waitOver();
        return callback.getList();
    }

    /**
     * 方法描述： 使用第三方解析验证 收费的 识别效率高 爬虫
     * 
     * @author TL
     * @date 2016年6月19日 下午3:01:41
     * @param parameterS
     * @return
     */
    public List<Parameter> enterCodeChargeCrawler(List<Parameter> parameterS) {
        Preconditions.checkNotNull(parameterS);
        class RunCallable implements Callable<Parameter> {
            private Parameter parameter = null;
            public RunCallable(Parameter parameter) {
                this.parameter = parameter;
            }
            @Override
            public Parameter call() throws Exception {
                Parameter par = null;
                do {
                    try {
                        par = new Parameter();
                        par = new XTY_Site().setParameter(parameter).enterCodeCharge().resultsOf();
                    } catch (Exception e) {
                        par = parameter;
                        parameter.setExc(e);
                    }
                } while (par.getExc()!=null||!Strings.isNullOrEmpty(par.getContent()));
                return par;
            }
        }
        // 创建线程池
        ExecutorService service = new ExecutorService(threadCount);
        ResultCallback callback = new ResultCallback();
        for (final Parameter parameter : parameterS) {
            service.addCallback(new RunCallable(parameter), callback);
        }
        service.waitOver();
        return callback.getList();
    }

    private class ResultCallback implements FutureCallback<Parameter> {
        private List<Parameter> list;

        public ResultCallback() {
            list = new ArrayList<Parameter>();
        }

        @Override
        public void onFailure(Throwable throwable) {
            throwable.printStackTrace();
        }

        @Override
        public void onSuccess(Parameter arg0) {
            list.add(arg0);
        }

        public List<Parameter> getList() {
            return list;
        }
    }

}
